package demo.spark.hurypoint.parser

import com.google.gson.{JsonElement, JsonObject, JsonParser, JsonSyntaxException}
import org.apache.spark.sql.{DataFrame, SparkSession}
import org.apache.spark.sql.types.DataType

/**
 * 点击事件解析器
 * @param sparkSession
 * @param structs 结构体
 */
class ClickEventParser(sparkSession: SparkSession,
                       structs: (String,DataType,Boolean)*
                      ) extends EventParser[DataFrame](sparkSession, structs) {

  override def prepare(origin: DataFrame, args: Any*): Unit = {
    super.prepare(origin, args);

    // register "udf" function for "args" parser.
    require(sparkSession != null)
    sparkSession.udf.register("parseArgs", (pageName: String, ctrlName: String, argsJson: String) => getArgsValue(pageName,ctrlName,argsJson))
  }

  override def parse(origin: DataFrame): DataFrame = {
    // Getting DataFrame of click event's core fields.
    var clickEventCoreFields: DataFrame = origin
      // filter by "event_type" for "click".
      .filter(row => row.getAs[String]("event_type").equals("click"))
      // find click event's page_name, ctrl_name, and args.
      .select("page_name", "ctrl_name","args");

    // register core fields as temp table.
    val tempTab = "temp_client_event_" + System.currentTimeMillis();
    clickEventCoreFields.createOrReplaceTempView(tempTab);

    // getting reported args to DataFrame.
    var aggregateCountDF: DataFrame = sparkSession.sqlContext
      .sql(s"select page_name, ctrl_name, args, parseArgs(page_name, ctrl_name, args) as arg from ${tempTab}")
      // filter careful fields.
      .select("page_name","ctrl_name","arg")
      // aggregate group by "page_name", "ctrl_name", "arg" for event occur counts.
      .groupBy("page_name","ctrl_name", "arg").count().as("count");

    // union to previous DataFrame, which has been dealed.
    dealDF = dealDF.unionByName(aggregateCountDF);
    dealDF
  }

  override def report(lineCount: Integer): Unit = {
    import sparkSession.sqlContext.implicits._;
    dealDF
      .groupBy("page_name","ctrl_name").sum("count")
      .toDF("page_name","ctrl_name","ctrl_name_click_total_count")
      .sort($"ctrl_name_click_total_count".desc)
      .show(lineCount);
  }


  // udf function for parse click event's "args".
  def getArgsValue(pageName: String, ctrlName: String, argsJson: String): String = {
    val jsonParser = new JsonParser()
    var args: Option[String] = None
    var jsonObj: JsonObject = null
    if (argsJson != null && argsJson.length() > 0) {
      try {
        var jsonEle: JsonElement = jsonParser.parse(argsJson);
        if(jsonEle.isJsonObject){
          jsonObj = jsonEle.getAsJsonObject;
        }else{
          jsonObj = jsonEle.getAsJsonArray.get(0).getAsJsonObject;
        }
      } catch {
        case ex: JsonSyntaxException => {
          println(s"JsonSyntaxException===>[${pageName}] [${ctrlName}] ${argsJson}")
        }
      }
    }
    if (jsonObj == null) {
      return ""
    }

    try {
      if (pageName.equals("MapHomeBoard")) {                                                  // 地图主页
        args = ctrlName match {
          case "guidance_mute_click" => Some("" + jsonObj.get("mute_status").getAsInt())     // 静音、解除静音
          case "rangeonmap_click" => Some("" + jsonObj.get("status").getAsInt())             // 进入/退出Range on map全览状态
          case _ => None
        }
      } else if (pageName.equals("SearchEntranceBoard")) {                                    // 搜索主页页面
        args = ctrlName match {
          case "home_click" => Some("" + jsonObj.get("home_status").getAsInt())              // 点击搜索页面的家时，家设置的状态
          case "home_waypoint_click" => Some("" + jsonObj.get("waypoint_oper").getAsInt())   // 有路线时，家添加为途经点或从途经点列表中删除时的操作类型
          case "comp_click" => Some("" + jsonObj.get("comp_status").getAsInt())              // 点击搜索页面的公司时，公司设置的状态
          case "comp_waypoint_click" => Some("" + jsonObj.get("waypoint_oper").getAsInt())   // 有路线时，公司添加为途经点或从途经点列表中删除时的操作类型
          case "history_click" => Some("" + jsonObj.get("history_type").getAsInt())          // 点击搜索历史列表记录时，记录类型
          case "history_action_click" => Some("" + jsonObj.get("action_type").getAsInt())    // 点击历史目的地设置为，按钮类型
          case "history_remove_click" => Some("" + jsonObj.get("history_type").getAsInt())   // 删除单条历史记录时，记录类型
          case "poi_type_click" => Some(jsonObj.get("cate").getAsString())                   // 点击搜索页面的类型时，类型编码
          case _ => None
        }

      } else if (pageName.equals("InputKeyWordSearchBoard")) {                                // 关键字搜索页
        args = ctrlName match {
          case "sug_click" => Some("" + jsonObj.get("sug_type").getAsInt())                  // 点击建议搜列表记录时的记录类型
          case "sug_action_click" => Some("" + jsonObj.get("action_type").getAsInt())        // 点击建议搜结果设置为时的按钮类型
          case "history_remove_click" => Some("" + jsonObj.get("history_type").getAsInt())   // 删除单条历史记录时，记录类型
          case _ => None
        }
      } else if (pageName.equals("SearchResultBoard")) {                                                                                                  // 搜索结果页
        args = ctrlName match {
          case "search_result_click" => {                                                                                                                 // 点击搜索结果，POI类型
            Some(if (jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").isJsonNull()) ""
            else jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").getAsString())
          }
          case "search_result_action_click" => {                                                                                                          // 点击搜索结果设置为，POI类型
            Some(if (jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").isJsonNull()) ""
            else jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").getAsString())
          }
          case _ => None
        }
      } else if (pageName.equals("MultiRouteBoard")) {                                          // 多条路线规划结果页
        args = ctrlName match {
          case "charge_dest_sug_click" => Some("" + jsonObj.get("epower").getAsInt())          // 点击终点无法到达的充电站搜索推荐，点击时车辆电量续航公里数
          case _ => None
        }
      } else if (pageName.equals("ExploreWayBoard")) {                                          // 探路页
        args = ctrlName match {
          case "guidance_mute_click" => Some("" + jsonObj.get("mute_status").getAsInt())      // 静音、解除静音
          case "main_side_road_click" => Some("" + jsonObj.get("oper_type").getAsInt())       // 主辅路切换，操作类型
          case "overpass_click" => Some("" + jsonObj.get("oper_type").getAsInt())             // 桥上桥下切换，操作类型
          case _ => None
        }
      } else if (pageName.equals("NavigationBoard")) {                                         // 实时导航页面
        args = ctrlName match {
          case "guidance_mute_click" => Some("" + jsonObj.get("mute_status").getAsInt())      // 静音、解除静音
          case "main_side_road_click" => Some("" + jsonObj.get("oper_type").getAsInt())       // 主辅路切换，操作类型
          case "overpass_click" => Some("" + jsonObj.get("oper_type").getAsInt())             // 桥上桥下切换，操作类型
          case "charge_sug_click" => Some("" + jsonObj.get("epower").getAsInt())              // 终点充电站点击查看，点击时车辆电量续航公里数
          case _ => None
        }
      } else if (pageName.equals("PoiDetailBoard")) {                                          // POI详情页
        args = ctrlName match {
          case "poi_detail_pic_click" => Some("" + jsonObj.get("map_navi_status").getAsInt()) // 点击POI图片，地图导航状态
          case "poi_detail_favor_click" => Some("" + jsonObj.get("favor_status").getAsInt())  // 点击POI收藏，收藏状态
          case "poi_detail_service_click" => Some(if(jsonObj.get("service").isJsonNull()) "" else jsonObj.get("service").getAsString())       // 点击业务服务入口，服务名称
          case "poi_detail_action_click" => Some("" + jsonObj.get("action_type").getAsInt())  // 点击POI设置为，按钮类型
          case _ => None
        }
      } else if (pageName.equals("FavoriteAddressBoard")) {                                                                                      // 我的收藏页
        args = ctrlName match {
          case "favor_remove_click" => {                                                                                                         // 删除单个收藏点，POI类型
            Some(if (jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").isJsonNull()) ""
            else jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").getAsString())
          }
          case "favor_click" => {                                                                                                               // 删除收藏夹列表记录，POI类型
            Some(if (jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").isJsonNull()) ""
            else jsonParser.parse(jsonObj.get("poi").getAsString()).getAsJsonObject().get("poi_cate").getAsString())
          }
          case "favor_action_click" => Some("" + jsonObj.get("action_type").getAsInt())                                                          // 点击收藏点设置为，按钮类型
          case _ => None
        }
      } else if (pageName.equals("SettingBoard")) {                                                  // 地图设置页面
        args = ctrlName match {
          case "tmc_overview_select" => Some("" + jsonObj.get("tmc_overview_status").getAsInt())    // 选择路况概览，路况概览选择状态
          case "navi_guidance_select" => Some("" + jsonObj.get("navi_guidance_status").getAsInt())  // 选择导航播报，播报选中状态
          case "assist_tmc_select" => Some("" + jsonObj.get("status").getAsInt())                   // 选择辅助路况播报，辅助播报状态
          case "assist_camera_select" => Some("" + jsonObj.get("status").getAsInt())                // 选择辅助电子眼播报，电子眼播报状态
          case "auto_scale_select" => Some("" + jsonObj.get("status").getAsInt())                   // 选择自动比例尺，自动比例尺开关状态
          case "tmc_select" => Some("" + jsonObj.get("status").getAsInt())                          // 选择实时路况，实时路况开关状态
          case "car_pic_select" => Some("" + jsonObj.get("car_pid").getAsInt())                     // 选择车标，车标ID
          case _ => None
        }
      } else {;}
    }catch {
      case ex: UnsupportedOperationException => None
    }

    args.getOrElse("")
  }
}
